using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Quartz;
using System.Text.Json;
using Uantek.Device.Communication.Models;
using Uantek.Device.Communication.Services.Interfaces;
using Uantek.Model.Mas;
using Uantek.Tasks;
using Uantek.ServiceCore.Services;
using Uantek.Service.Mas.IService;
using Infrastructure;

namespace Uantek.Device.Communication.Jobs
{
    /// <summary>
    /// 设备通信任务，集成Uantek.Tasks调度器
    /// </summary>
    [DisallowConcurrentExecution]
    public class DeviceCommunicationJob : JobBase, IJob
    {
        private readonly ILogger<DeviceCommunicationJob> _logger;
        private readonly IServiceProvider _serviceProvider;

        public DeviceCommunicationJob()
        {
            _logger = (ILogger<DeviceCommunicationJob>)App.GetRequiredService(typeof(ILogger<DeviceCommunicationJob>));
            _serviceProvider = App.ServiceProvider;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            await ExecuteJob(context, async () =>
            {
                await ExecuteDeviceCommunicationAsync(context);
            });
        }

        private async Task ExecuteDeviceCommunicationAsync(IJobExecutionContext context)
        {
            using var scope = _serviceProvider.CreateScope();
            var deviceCommunicationService = scope.ServiceProvider.GetRequiredService<IDeviceCommunicationService>();
            var dataCollectionService = scope.ServiceProvider.GetRequiredService<IDataCollectionService>();
            var mqttPublishService = scope.ServiceProvider.GetRequiredService<IMqttPublishService>();
            var equipmentParameterService = scope.ServiceProvider.GetService<IMasEquipmentParameterService>();

            try
            {
                _logger.LogInformation("开始执行设备通信任务");

                // 获取任务参数
                var jobDataMap = context.JobDetail.JobDataMap;
                var deviceIds = GetJobParameter<string[]>(jobDataMap, "deviceIds", new string[0]);
                var enableAutoCollection = GetJobParameter<bool>(jobDataMap, "enableAutoCollection", true);
                var collectionInterval = GetJobParameter<int>(jobDataMap, "collectionInterval", 5000);
                var enableMqttPublish = GetJobParameter<bool>(jobDataMap, "enableMqttPublish", true);

                var processedDevices = 0;
                var failedDevices = 0;

                // 如果未指定设备ID，则处理所有启用的设备参数
                if (deviceIds.Length == 0 && equipmentParameterService != null)
                {
                    var equipmentParameters = await GetEnabledEquipmentParametersAsync(equipmentParameterService);
                    deviceIds = equipmentParameters.Select(p => $"device_{p.EquipmentId}_{p.Id}").ToArray();
                }

                foreach (var deviceId in deviceIds)
                {
                    try
                    {
                        await ProcessDeviceAsync(deviceId, deviceCommunicationService, dataCollectionService, 
                                               mqttPublishService, enableAutoCollection, collectionInterval, enableMqttPublish);
                        processedDevices++;
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, $"处理设备 {deviceId} 失败");
                        failedDevices++;
                    }
                }

                _logger.LogInformation($"设备通信任务执行完成，处理设备数: {processedDevices}，失败设备数: {failedDevices}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "设备通信任务执行失败");
                throw;
            }
        }

        private async Task ProcessDeviceAsync(string deviceId, IDeviceCommunicationService deviceCommunicationService,
                                            IDataCollectionService dataCollectionService, IMqttPublishService mqttPublishService,
                                            bool enableAutoCollection, int collectionInterval, bool enableMqttPublish)
        {
            // 检查设备状态
            var deviceStatus = await deviceCommunicationService.GetDeviceStatusAsync(deviceId);
            if (deviceStatus == null)
            {
                _logger.LogWarning($"设备 {deviceId} 状态信息不存在，跳过处理");
                return;
            }

            // 如果设备未连接，尝试连接
            if (!deviceStatus.IsConnected)
            {
                var connectResult = await deviceCommunicationService.ConnectDeviceAsync(deviceId);
                if (!connectResult.Success)
                {
                    _logger.LogWarning($"设备 {deviceId} 连接失败: {connectResult.Message}");
                    return;
                }
            }

            // 启动数据收集
            if (enableAutoCollection)
            {
                var collectionResult = await dataCollectionService.StartCollectionAsync(deviceId, collectionInterval);
                if (!collectionResult.Success)
                {
                    _logger.LogWarning($"设备 {deviceId} 启动数据收集失败: {collectionResult.Message}");
                }
            }

            // 获取实时数据并发布到MQTT
            if (enableMqttPublish && mqttPublishService.IsConnected)
            {
                var realTimeData = await dataCollectionService.GetRealTimeDataAsync(deviceId);
                if (realTimeData != null)
                {
                    var publishResult = await mqttPublishService.PublishDeviceDataAsync(realTimeData);
                    if (!publishResult.Success)
                    {
                        _logger.LogWarning($"设备 {deviceId} MQTT数据发布失败: {publishResult.Message}");
                    }
                }

                // 发布设备状态
                var statusPublishResult = await mqttPublishService.PublishDeviceStatusAsync(deviceStatus);
                if (!statusPublishResult.Success)
                {
                    _logger.LogWarning($"设备 {deviceId} MQTT状态发布失败: {statusPublishResult.Message}");
                }
            }

            _logger.LogDebug($"设备 {deviceId} 处理完成");
        }

        private async Task<List<MasEquipmentParameter>> GetEnabledEquipmentParametersAsync(IMasEquipmentParameterService equipmentParameterService)
        {
            try
            {
                // 获取所有启用的设备参数
                var parameters = await equipmentParameterService.GetListAsync(p => p.UseYN == 1);
                return parameters.ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取启用的设备参数失败");
                return new List<MasEquipmentParameter>();
            }
        }

        private T GetJobParameter<T>(JobDataMap jobDataMap, string key, T defaultValue)
        {
            try
            {
                if (jobDataMap.ContainsKey(key))
                {
                    var value = jobDataMap[key];
                    if (value is T directValue)
                    {
                        return directValue;
                    }
                    
                    if (value is string stringValue && !string.IsNullOrEmpty(stringValue))
                    {
                        if (typeof(T) == typeof(string[]))
                        {
                            return (T)(object)JsonSerializer.Deserialize<string[]>(stringValue);
                        }
                        else if (typeof(T) == typeof(bool))
                        {
                            return (T)(object)bool.Parse(stringValue);
                        }
                        else if (typeof(T) == typeof(int))
                        {
                            return (T)(object)int.Parse(stringValue);
                        }
                        else
                        {
                            return (T)Convert.ChangeType(stringValue, typeof(T));
                        }
                    }
                }
                return defaultValue;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, $"解析任务参数 {key} 失败，使用默认值: {defaultValue}");
                return defaultValue;
            }
        }
    }

    /// <summary>
    /// 设备通信任务配置
    /// </summary>
    public class DeviceCommunicationJobConfig
    {
        /// <summary>
        /// 设备ID列表
        /// </summary>
        public string[] DeviceIds { get; set; } = new string[0];

        /// <summary>
        /// 是否启用自动数据收集
        /// </summary>
        public bool EnableAutoCollection { get; set; } = true;

        /// <summary>
        /// 数据收集间隔（毫秒）
        /// </summary>
        public int CollectionInterval { get; set; } = 5000;

        /// <summary>
        /// 是否启用MQTT发布
        /// </summary>
        public bool EnableMqttPublish { get; set; } = true;

        /// <summary>
        /// 是否启用设备状态监控
        /// </summary>
        public bool EnableStatusMonitoring { get; set; } = true;

        /// <summary>
        /// 连接超时时间（毫秒）
        /// </summary>
        public int ConnectionTimeout { get; set; } = 10000;

        /// <summary>
        /// 最大重试次数
        /// </summary>
        public int MaxRetryCount { get; set; } = 3;

        /// <summary>
        /// 任务执行间隔（Cron表达式）
        /// </summary>
        public string CronExpression { get; set; } = "0 */1 * * * ?"; // 每分钟执行一次

        /// <summary>
        /// 转换为JobDataMap
        /// </summary>
        /// <returns></returns>
        public JobDataMap ToJobDataMap()
        {
            var dataMap = new JobDataMap();
            dataMap.Put("deviceIds", JsonSerializer.Serialize(DeviceIds));
            dataMap.Put("enableAutoCollection", EnableAutoCollection.ToString());
            dataMap.Put("collectionInterval", CollectionInterval.ToString());
            dataMap.Put("enableMqttPublish", EnableMqttPublish.ToString());
            dataMap.Put("enableStatusMonitoring", EnableStatusMonitoring.ToString());
            dataMap.Put("connectionTimeout", ConnectionTimeout.ToString());
            dataMap.Put("maxRetryCount", MaxRetryCount.ToString());
            return dataMap;
        }
    }
}